home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / muds / lpmud312.tar / lpmud312 / parse_old.c < prev    next >
C/C++ Source or Header  |  1992-01-11  |  27KB  |  1,054 lines

  1. /*
  2.  
  3.   Pattern Parser package for LPmud, JnA 1990
  4.  
  5.   Ver 2.0
  6.  
  7.   If you have questions or complaints about this code please refer them
  8.   to jna@cd.chalmers.se
  9.  
  10.   This is the old version of parse_command() used in compatibility mode.
  11.  
  12. */
  13.  
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <ctype.h>
  17. #include <time.h>
  18. #include "lint.h"
  19. #include "interpret.h"
  20. #include "config.h"
  21. #include "object.h"
  22. #include "wiz_list.h"
  23.  
  24. #define VALUE struct svalue
  25. #define OBJECT struct object
  26. #define VECTOR struct vector
  27. #define SVALUE struct svalue
  28. #define LVALUE struct svalue
  29.  
  30. extern char *string_copy PROT((char *)), *xalloc PROT((int));
  31. extern int o_flag, d_flag; /* for debugging purposes */
  32. extern SVALUE const0, const1;
  33.  
  34. #ifndef tolower            /* On some systems this is a function */
  35. extern int tolower PROT((int));
  36. #endif
  37.  
  38. #ifdef COMPAT_MODE
  39. /*****************************************************
  40.  
  41.   This is the parser
  42.  
  43.  
  44.   Left to do 910723:
  45.  
  46.   Fix so alternatives possible after %s in a pattern 
  47.  
  48. */
  49. /*
  50.   Doc for LPC function
  51.  
  52. int parse_command(string,ob/arr,string,destargs...)
  53.  
  54.     parse        Returns 1 if pattern matches
  55.  
  56.     string        Given command
  57.     ob/arr        if arr 
  58.                 array holding the accessible objects
  59.             if ob
  60.                 object from which to recurse and create
  61.                 the list of accessible objects, normally
  62.                 ob = environment(this_player())
  63.     string        Parsepattern as list of words and formats:
  64.             Example string = " 'get' / 'take' %i "
  65.             Syntax:
  66.                 'word'         obligatory text
  67.                 [word]        optional text
  68.                 /        Alternative marker
  69.                 %o        Single item, object
  70.                 %l        Single living object
  71.                 %s        Any text
  72.                 %w              Any word
  73.                 %p        Preposition
  74.                 %i        Any items
  75.                 %d              Number 0- or tx(0-99)
  76.  
  77.     destargs    This is the list of result variables as in sscanf
  78.             One variable is needed for each %_
  79.             The return types of different %_ is:
  80.             %o    Returns an object
  81.             %l    Returns an object
  82.             %s    Returns a string of words
  83.             %w      Returns a string of one word
  84.             %p    Can on entry hold a list of word in array
  85.                 or an empty variable
  86.                 Returns:
  87.                    if empty variable: a string
  88.                    if array: array[0]=matched word
  89.             %i    Returns a special array on the form:
  90.                 [0] = (int) +(wanted) -(order) 0(all)
  91.                 [1..n] (object) Objectpointers
  92.             %d      Returns a number
  93.             
  94. Example:
  95.  
  96.  parse_command("take apple",environment(this_player()),
  97.  " 'get' / 'take' %i ",items);
  98.  
  99.  
  100. */ 
  101.  
  102. /* Hardcoded function names to call in LPC objects
  103. */
  104. #define QIDFUNC "id"                /* Func to query in objects to ack name */
  105. #define QPLURIDFUNC "plural_id"     /* As Id but pluralform of name */
  106. #define QADJFUNC "adjectiv_id"      /* As Id but ack adjectiv not name */
  107. #define QSHORTFUNC "short"          /* Objects shortdescription */
  108.  
  109. #define EQ(x,y) (strcmp(x,y)==0)
  110. #define EQN(x,y) (strncmp(x,y,strlen(x))==0)
  111. #define EMPTY(x) (strcmp(x,"")==0)
  112. #define COPY(x) (strcpy((char*)xalloc(strlen(x)+1),x))
  113.  
  114. #define KLUDGELEN   200            /* How long should strings be */
  115.  
  116. struct altern_objects {
  117.   OBJECT *ao_obj;
  118.   struct altern_objects *next;
  119. };
  120.  
  121. int gDebug=0;
  122. char gMword[KLUDGELEN];            /* Text inom '' och [] */
  123. char gFword[KLUDGELEN];            /* Temp word gotten by getfirst() */
  124. struct altern_objects *gOblist;    /* List of accessible objects */
  125. char gAdjective[4*KLUDGELEN];      /* all adjectives before objname */
  126. LVALUE *gCarg;                     /* Current argument to %_ */
  127. int gWantnum;                      /* Number of wanted items 0 = all */
  128. struct altern_objects *gPobjects;  /* List of parsed objects */
  129. LVALUE *gTxarg;                    /* Argument of LPCvariable to store %s  */
  130. LVALUE *gForprepos;                /* Save arg* here for findprepos */
  131. LVALUE *gTopStack;                 /* arg* to arg after my last */
  132.  
  133. #define EP 0          /* End Parse marker */
  134. #define SI 1          /* %o single item */
  135. #define IT 2          /* %i  items */
  136. #define US 3          /* %l  single living object */
  137. #define PP 4          /* %p  prepositions */
  138. #define TX 5          /* %s  string of words */
  139. #define DTX 6         /* 'word' */
  140. #define OTX 7         /* [word] */
  141. #define ALT 8         /* /   alternates */
  142. #define W1 9          /* %w  string of one word */
  143. #define NUM 10        /* %d  integer */
  144.  
  145. /* Search string in reverse order, I should replace it with strrchr I know :)
  146. */
  147. char *backstrchr (apa, ch)
  148.     char *apa;
  149.     char ch;
  150. {
  151.   char *sp;
  152.  
  153.   sp = &apa[strlen(apa)];
  154.   while (sp>apa) {
  155.     if (*sp==ch) return sp+1;
  156.     sp--;
  157.   }
  158.   return 0;
  159. }
  160.  
  161. /* Convert string to lowercase
  162. */
  163. char *lowercase (apa)
  164.     char *apa;
  165. {
  166.   char *bepa;
  167.  
  168.   bepa = apa;
  169.   while (*bepa) {
  170.     if ((*bepa>'A') && (*bepa<'a')) (*bepa)+='a'-'A';
  171.     bepa++;
  172.   }
  173.   return apa;
  174. }
  175.  
  176. /* Add all objects in the inventory of 'first' and itself to the list 'parent'
  177.    antal holds the number of elements in the 'parent' list.
  178. */
  179. void fixlist (first, parent, antal)
  180.     OBJECT *first;
  181.     struct altern_objects **parent;
  182.     int *antal;
  183. {
  184.   OBJECT *cur;
  185.   struct altern_objects *this,*taill;
  186.   cur=first; this= *parent;
  187.   if (!cur) return;
  188.   while (cur) {
  189.     if (cur->contains) fixlist(cur->contains,&this,antal);
  190.     taill=this;
  191.     this=(struct altern_objects *) xalloc(sizeof(struct altern_objects));
  192.     this->ao_obj=cur; (*antal)++;
  193.     add_ref(cur,"parse->fixlist");
  194.     if (gDebug) fprintf(stderr," Obj:%s ,",cur->name);
  195.     this->next=taill; cur=cur->next_inv;
  196.   }
  197.   *parent=this;
  198. }
  199.  
  200. /* Create a list of the theoretically accessible objects from 'src'
  201. */
  202. int makeobjlist (alist, src)
  203.     struct altern_objects **alist;
  204.     OBJECT *src;
  205. {
  206.   OBJECT *env,*cur;
  207.   struct altern_objects *this;
  208.   int cnt;
  209.   *alist=0;
  210.   if (!src) env=command_giver->super;
  211.   else env=src;
  212.   if (!env) return 0;
  213.   if (gDebug) fprintf(stderr,"Make list: %s\n",env->name);
  214.   if (!(env->contains)) return 0;
  215.   cur=env->contains;
  216.   this=0; cnt=0;
  217.   fixlist(cur,&this,&cnt); *alist=this;
  218.   return cnt;
  219. }
  220.  
  221. /* Routines to use for alternate filters
  222. */
  223.  
  224. /* Return number of objects in the list
  225. */
  226. int itnumalt()
  227.   int ant;
  228.   struct altern_objects *ao;
  229.  
  230.   ant=0; ao=gPobjects;
  231.   while (ao) {
  232.     ant++;
  233.     ao=ao->next;
  234.   }
  235.   return ant;
  236. }
  237.  
  238. /* Return a pointer to the numbered element of the list
  239. */ 
  240. OBJECT *italt (a)
  241.     int a;
  242.   int ant;
  243.   struct altern_objects *ao;
  244.  
  245.   ant=0; ao=gPobjects;
  246.   while (ao) {
  247.     ant++;
  248.     if (ant==a) return ao->ao_obj;
  249.     ao=ao->next;
  250.   }
  251.   return 0;
  252. }
  253.  
  254. /* Free the list, parameter bas is obsolete
  255. */
  256. void italt_new ()
  257. {
  258.  
  259.   /* Free p} altern_objects listan */
  260.   struct altern_objects *ao;
  261.   struct altern_objects *ao2;
  262.  
  263.   if (gDebug) fprintf(stderr,"Clearing italt\n");
  264.   ao2=ao=gPobjects; gPobjects=0;
  265.   while (ao) {
  266.     ao=ao->next;
  267.     free_object(ao2->ao_obj,"parse->italt_new()");
  268.     free((char *)ao2); 
  269.     ao2=ao;
  270.   }
  271. }
  272.  
  273. /* Create the list as all the theoretically accessible objects
  274. */
  275. void italt_loadall()
  276. {
  277.   if (gPobjects) italt_new();
  278.   makeobjlist(&gPobjects,0);
  279. }
  280.  
  281. /* Put an object at the end of the list
  282. */
  283. void italt_put (obj)
  284.     OBJECT *obj;
  285. {
  286.   struct altern_objects *ao,*old;
  287.  
  288.   if (gDebug) fprintf(stderr,"Putting: %s",obj->name);
  289.   ao=gPobjects; old=ao;
  290.   while (ao) {
  291.     old=ao; ao=ao->next;
  292.   }
  293.   ao=(struct altern_objects *) xalloc(sizeof(struct altern_objects));
  294.   if (old) old->next=ao; 
  295.   else gPobjects=ao;
  296.   ao->ao_obj=obj; ao->next=0;
  297.   add_ref(obj,"parse->italt_put()");
  298.   if (gDebug) fprintf(stderr,"..done\n");
  299. }
  300.  
  301.  
  302. /* Put first word of cmd in gFword and point to next word
  303. */
  304. char *getfirst (cmd)
  305.     char **cmd;
  306. {
  307.   int pos,inqoute;
  308.   char ch,*st;
  309.  
  310.   st= *cmd; strcpy(gFword,""); if (st[0]==0) return gFword;
  311.   ch=' '; pos=0; inqoute=0; 
  312.   while ((st[0]<=' ') && (st[0])) st++; /* Skip leading spaces */
  313.   if ((st[0]=='\'') || (st[0]=='[')) {
  314.     inqoute=1; ch=st[0]; gFword[0]=st[0]; pos=1; st++;
  315.   }
  316.   if (ch=='[') ch=']';
  317.   while ((pos<(KLUDGELEN-1)) && (st[0]) && (st[0]!=ch)) {
  318.     gFword[pos++]=st[0]; st++;
  319.     if ((st[0]) && (st[0]<' ')) st[0]=' ';  /* Replace ctrl chars */
  320.   }
  321.   if ((inqoute) && (pos<(KLUDGELEN-1))) {
  322.     gFword[pos++]=ch; if (st[0]) st++;
  323.   }
  324.   gFword[pos]=0;  /* fprintf(stderr,"{%s}",gFword); */
  325.   *cmd=st;
  326.   return gFword;
  327. }
  328.  
  329. /* Put first word of cmd in gFword
  330.    without incrementing the callers pointer in the command string
  331. */
  332. char *lookfirst (cmd)
  333.     char *cmd;
  334. {
  335.   return getfirst(&cmd);
  336. }     
  337.  
  338. /* Call object function in LPC
  339. */
  340. int call_obj (fnamn, on, apa)
  341.     char *fnamn;
  342.     OBJECT *on;
  343.     char *apa;
  344. {
  345.   struct svalue *ret;
  346.   
  347.   if (gDebug) fprintf(stderr,"Calling %s in %s with %s\n",fnamn,on->name,apa);
  348.   push_constant_string(apa);
  349.   ret = apply(fnamn,on,1);
  350.   if (!ret) return 0;
  351.   if ( ret->type == T_NUMBER) return ret->u.number;
  352.   return 0;
  353. }
  354.  
  355. /* Change a noun in pluralform to a noun in singularform
  356. */
  357. char *singfix (str)
  358.     char *str;
  359. {
  360.   static char sing[KLUDGELEN];
  361.   char *sp;
  362.   int sl;
  363.  
  364.   sl=strlen(str); if (sl<2) return str;
  365.   sp= &str[sl-3]; strcpy(sing,str); sing[sl-3]=0;
  366.   if (gDebug) fprintf(stderr,"To singular (%s) end(%s) begin(%s)\n",str,sp,sing);
  367.   if (EQ(str,"corpses")) return "corpse";
  368.   if (EQ(sp,"ses")) return strcat(sing,"s");
  369.   else if (EQ(sp,"xes")) return strcat(sing,"x");
  370.   else if (EQ(sp,"hes")) return strcat(sing,"h");
  371.   else if (EQ(sp,"ies")) return strcat(sing,"y");
  372.   else if (EQ(sp,"ves")) return strcat(sing,"fe");
  373.   else if (sp[2]=='s') {
  374.     strcat(sing,sp); sing[sl-1]=0;
  375.     return sing;
  376.   }
  377.   if (EQ(str,"teeth")) return "tooth";
  378.   if (EQ(str,"feet")) return "foot";
  379.   if (EQ(str,"men")) return "man";
  380.   if (EQ(str,"women")) return "woman";
  381.   if (EQ(str,"children")) return "child";
  382.   if (EQ(str,"sheep")) return "sheep";
  383.   return str;
  384. }
  385.     
  386. /* Checks with obj in gOblist to see if it accepts all gAdjectives in adjs
  387.    Used when name of object not known, i.e cmds like: 'get all the red ones'
  388.    if func QADJFUNC doesn't exist in obj last word of QSHORTFUNC is used
  389.    as object name and set as suffix to the adjective in call to id()
  390. */
  391. int matchadjective (adjs)
  392.     char *adjs;
  393. {
  394.  
  395.   char ad[KLUDGELEN],tot[2*KLUDGELEN],*sp,*sp2;
  396.   struct altern_objects *ao;
  397.   OBJECT *on;
  398.   struct svalue *ret;
  399.  
  400.   ao=gOblist;
  401.   while (ao) {
  402.     on=ao->ao_obj;
  403.     sp=adjs;
  404.     while ((on) && (sp) && (*sp)) {
  405.       while (*sp==' ') sp++;
  406.       sp2=strchr(sp,' ');  
  407.       if (sp2) {
  408.     *sp2=0;
  409.     strcpy(ad,sp); *sp2=' '; sp=sp2;
  410.     if (!call_obj(QADJFUNC,on,ad)) on=0; /* Not ok */
  411.       }
  412.       sp=sp2;
  413.     }
  414.     if (on) italt_put(on);
  415.     else {
  416.       on=ao->ao_obj;
  417.       ret = apply(QSHORTFUNC,on,0);
  418.       if (ret->type==T_STRING) {
  419.     sp=ret->u.string; sp2=backstrchr(sp,' ');
  420.     if (sp2) sp=sp2;
  421.     sprintf(tot,"%s%s",adjs,sp); lowercase(tot);
  422.     if (!call_obj(QIDFUNC,on,tot)) on=0;
  423.       }
  424.       else on=0;
  425.     }
  426.     if (on) italt_put(on);
  427.     ao=ao->next;
  428.   }
  429.   return itnumalt();
  430. }
  431.  
  432. /* Decide if a word is a general word of type: those, ones
  433. */
  434. int check_for_general (onam, plur)
  435.     char *onam;
  436.     int plur;
  437. {
  438.  
  439.   static char* plurpron[] = {"those","them","these","ones","$"};
  440.   static char* singpron[] = {"this","one","it","$"};
  441.   int ilop;
  442.   
  443.   if (EMPTY(onam)) return 0;
  444.   if (plur) {
  445.     ilop=0; 
  446.     while (!EQ(plurpron[ilop],"$")) if (EQ(plurpron[ilop++],onam)) return 1;
  447.   }
  448.   else {
  449.     ilop=0; 
  450.     while (!EQ(singpron[ilop],"$")) if (EQ(singpron[ilop++],onam)) return 1;
  451.   }
  452.   return 0;
  453. }
  454.  
  455. int order_num (wd)
  456.     char *wd;
  457. { /* Only positive numbers and zero */
  458.  
  459.   static char *onums[] = {"first","second","third","fourth","fifth","sixth",
  460.           "seventh","eighth","nineth","tenth",
  461.           "eleventh","twelfth","thirteenth","fourteenth","fifteenth","sixteenth",
  462.           "seventeenth","eighteenth","nineteenth","dummy"};
  463.   static char *onumt[] = {"twenty","thirty","forty","fifty","sixty","seventy",
  464.           "eighty","ninety"};
  465.   static char *onumta[] = {"twentieth","thirtieth","fortieth","fiftieth","sixtieth","seventieth",
  466.           "eightieth","ninetieth"};
  467.  
  468.   char ns[KLUDGELEN];
  469.  
  470.   int ilop,nm;
  471.  
  472.   if (EMPTY(wd)) return -1;
  473.   for (ilop=1;ilop<20;ilop++) {
  474.     if (EQ(onums[ilop-1],wd)) return ilop;
  475.   }
  476.   for (nm=0;nm<8;nm++) for (ilop=0;ilop<9;ilop++) {
  477.     if (ilop>0) {
  478.     sprintf(ns,"%s%s",onumt[nm],onums[ilop-1]);
  479.     if (EQ(ns,wd)) return 20+nm*10+(ilop);
  480.     } else
  481.     if (EQ(onumta[nm],wd)) return 20+nm*10+(ilop);
  482.   }
  483.   return -1;
  484. }
  485.  
  486. int numeric (wd)
  487.     char *wd;
  488. { /* Only positive numbers and zero */
  489.  
  490.   static char *nums[] = {"one","two","three","four","five","six",
  491.           "seven","eight","nine","ten",
  492.           "eleven","twelve","thirteen","fourteen","fifteen","sixteen",
  493.           "seventeen","eighteen","nineteen"};
  494.   static char *numt[] = {"twenty","thirty","forty","fifty","sixty","seventy",
  495.           "eighty","ninety"};
  496.  
  497.   char ns[KLUDGELEN];
  498.  
  499.   int ilop,nm;
  500.  
  501.   if (EMPTY(wd)) return -1;
  502.   if (sscanf(wd,"%d",&nm)) return (nm>=0) ? nm : -1;
  503.   if ((EQ(wd,"a")) || (EQ(wd,"an"))) return 1;
  504.   for (ilop=1;ilop<20;ilop++) if (EQ(nums[ilop-1],wd)) return ilop;
  505.   for (nm=0;nm<8;nm++) for (ilop=0;ilop<9;ilop++) {
  506.     if (ilop>0) {
  507.     sprintf(ns,"%s%s",numt[nm],nums[ilop-1]);
  508.     if (EQ(ns,wd)) return 20+nm*10+(ilop);
  509.     }
  510.     else
  511.     if (EQ(numt[nm],wd)) return 20+nm*10+(ilop);
  512.   }
  513.   return -1;
  514. }
  515.  
  516. /* Searches commandstring for "adj1 adj2 ... adjN objectname"
  517.    Stores words before name in string: gAdjective, as "adj1 adj2 adj3 "
  518. */
  519. OBJECT *matchobject2 (cmd, plur)
  520.     char **cmd;
  521.     int plur;
  522.   OBJECT *on;
  523.   struct altern_objects *ao;
  524.   char *st,*ocmd,totname[2*KLUDGELEN],tot2[2*KLUDGELEN];
  525.  
  526.   ocmd= *cmd; strcpy(gAdjective,"");
  527.   st=lowercase(getfirst(cmd)); 
  528.   while (st[0]) {
  529.     if (check_for_general(st,plur)) {
  530.       if (matchadjective(gAdjective)) return italt(1);
  531.     }
  532.     sprintf(totname,"%s%s",gAdjective,st);
  533.     if (plur) sprintf(tot2,"%s%s",gAdjective,singfix(st));
  534.     ao=gOblist; 
  535.     while (ao) {
  536.       on=0;
  537.       if (plur) {
  538.     if (call_obj(QPLURIDFUNC,ao->ao_obj,totname)) on=ao->ao_obj;
  539.     else if (call_obj(QIDFUNC,ao->ao_obj,tot2)) on=ao->ao_obj;
  540.       }
  541.       else if (call_obj(QIDFUNC,ao->ao_obj,totname)) on=ao->ao_obj;
  542.       if (on) italt_put(on);
  543.       ao=ao->next;
  544.     }
  545.     if (!itnumalt()) {
  546.       strcat(gAdjective,st); strcat(gAdjective," ");
  547.       st=lowercase(getfirst(cmd)); 
  548.     }
  549.     else st[0]=0;
  550.   }
  551.   if (itnumalt()) return italt(1);
  552.   *cmd=ocmd; return 0;
  553. }
  554.  
  555. /* Search the command for valid object description
  556. */
  557. OBJECT *finditem (cmd, plur)
  558.     char **cmd;
  559.     int plur;
  560.   int nm;
  561.   OBJECT *pn;
  562.   char *ocmd,w1[KLUDGELEN];
  563.   
  564.   ocmd= *cmd; strcpy(w1,lowercase(getfirst(cmd)));
  565.   if (gDebug) fprintf(stderr,"FO (plur=%d): %s\n",plur,ocmd);
  566.   italt_new(); /* Clear alternate list */
  567.   gWantnum=1; /* Antal objekt som anv{ndaren vill ta */
  568.   if (EMPTY(w1)) {
  569.     *cmd=ocmd;
  570.     return 0;
  571.   }
  572.  
  573.   /* Must be hardcode skipped for recursive with plural
  574.    */
  575.   if (EQ("the",w1)) {
  576.     if (gDebug) fprintf(stderr,"Skip 'the'\n");
  577.     *cmd=ocmd; getfirst(cmd); 
  578.     if ((pn=finditem(cmd,plur))) return pn;
  579.     else { *cmd=ocmd; return 0; }
  580.   }
  581.   
  582.   /* Check things like: some <objname>
  583.    */
  584.   else if ((EQ("some",w1)) && (plur==0)) {
  585.     *cmd=ocmd; getfirst(cmd);
  586.     /* Skip of in : some of the bottles */
  587.     if (EQ(lowercase(lookfirst(*cmd)),"of")) getfirst(cmd);
  588.  
  589.     nm = random_number(6) + 2; /* some objects are random:2-7 */
  590.     if (gDebug) fprintf(stderr,"some rnd = %d\n",nm);
  591.     if ((pn=finditem(cmd,1))) { 
  592.       gWantnum=nm; 
  593.       return pn; 
  594.     }
  595.   }
  596.   
  597.   /* Check things like: three <objname>
  598.    */
  599.   else if ( (plur==0) && ((nm=numeric(w1))>0) ) {
  600.     if (gDebug) fprintf(stderr,"Numeral: %d (%s)\n",nm,w1);
  601.     *cmd=ocmd; getfirst(cmd);
  602.     /* Skip of in : two of the bottles */
  603.     if (EQ(lowercase(lookfirst(*cmd)),"of")) getfirst(cmd);
  604.     if ((pn=finditem(cmd,nm-1))) {
  605.       gWantnum=nm; return pn;
  606.     }
  607.   }
  608.   
  609.   /* Check things like: third <objname>
  610.    */
  611.   else if ( (plur==0) && ((nm=order_num(w1))>0) ) {
  612.     if (gDebug) fprintf(stderr,"Order: %d (%s)\n",nm,w1);
  613.     *cmd=ocmd; getfirst(cmd);
  614.     /* Skip of in : second of the bottles */
  615.     if (EQ(lowercase(lookfirst(*cmd)),"of")) {
  616.       getfirst(cmd);
  617.       if ((pn=finditem(cmd,1))) { /* Fix second of the bottles */
  618.     gWantnum= -nm; return pn;
  619.       }
  620.     }
  621.     else {
  622.       if ((pn=finditem(cmd,0))) { /* Fix second bottle */
  623.     gWantnum = -nm; return pn;
  624.       }
  625.     }
  626.   }
  627.   
  628.   
  629.   /* Check things like: all <objname>
  630.    */
  631.   else if ((EQ("all",w1)) && (plur==0)) {
  632.     if (gDebug) fprintf(stderr,"All found\n");
  633.     *cmd=ocmd; getfirst(cmd);
  634.     /* Skip of in : all of the bottles */
  635.     if (EQ(lowercase(lookfirst(*cmd)),"of")) { getfirst(cmd); }
  636.     if ((pn=finditem(cmd,1))) { /* Handle: get all apples */
  637.       gWantnum=0; /* Antal objekt som anvandaren vill ta 0 == all */
  638.       return pn;
  639.     }
  640.     else { /* Handle: get all */
  641.       italt_loadall(); pn=(OBJECT *) italt(1); 
  642.       gWantnum=0; /* Antal objekt som anvandaren vill ta 0 == all */
  643.     }
  644.   }
  645.   
  646.   /* Search for: adj1 adj2 ... adjN objectname
  647.    */
  648.   else {
  649.     *cmd=ocmd; if (gDebug) fprintf(stderr,"Objtry: %s\n",ocmd);
  650.     if (plur) pn=matchobject2(cmd,plur);
  651.     else { /* Standard singular */
  652.       pn=matchobject2(cmd,0); 
  653.       if (!pn) { /* Handle things of type: get apples */
  654.     pn=matchobject2(cmd,1); 
  655.     if (pn) gWantnum = 0; /* Default this to all */
  656.       }
  657.     }
  658.     if (gDebug) fprintf(stderr,"Done matchobject in finditem.\n");
  659.   }
  660.   
  661.   if (pn == 0) *cmd=ocmd;
  662.   if (gDebug) fprintf(stderr,"Done finditem.\n");
  663.   return pn;
  664. }
  665.  
  666. /* Find match to a %i in pattern
  667. */
  668. int findobject (cmd)
  669.     char **cmd;
  670. {
  671.   int nm,s;
  672.   OBJECT *ob;
  673.   
  674.   if (finditem(cmd,0)) {
  675.     if (gCarg) {
  676.       VECTOR *p;
  677.       if (gDebug) fprintf(stderr,"Assign array\n");
  678.       nm=itnumalt();
  679.       p=(VECTOR *)allocate_array(nm+1);
  680.       p->item[0].type = T_NUMBER;
  681.       p->item[0].u.number = gWantnum;
  682.  
  683.       /* Make array in reverse order from italt() because
  684.          makeobjlist() has reversed the order on entry
  685.       */
  686.       for (s=1;s<=nm;s++) {
  687.     p->item[s].type = T_OBJECT;
  688.     p->item[s].u.ob = ob = italt(nm+1-s);
  689.     if (!ob) if (gDebug) fprintf(stderr,"No object from italt %d\n",s);
  690.     if (ob) add_ref(ob,"parse_command");
  691.       }
  692.       free_svalue(gCarg->u.lvalue);
  693.       gCarg->u.lvalue->type = T_POINTER;
  694.       gCarg->u.lvalue->u.vec = p;
  695.       gCarg->u.lvalue->u.vec->ref++;
  696.  
  697.       if (gDebug) fprintf(stderr,"Assign array2\n");
  698.     }
  699.     return 1;
  700.   }
  701.   return 0;
  702. }
  703.  
  704. /* Find match to a %l in pattern
  705. */
  706. OBJECT *findplay (cmd)
  707.     char **cmd;
  708.   OBJECT *pn;
  709.   char w1[KLUDGELEN];
  710.  
  711.   strcpy(w1,lowercase(lookfirst(*cmd)));
  712.   /* can be fixed later with call to LPC command_giver->query_real_name() 
  713.   if (EQ(w1,"me")) strcpy(w1,getmyname_jp());
  714.   if (EQ(w1,"myself")) strcpy(w1,getmyname_jp());
  715.   */
  716.   pn=(OBJECT *) find_living_object(w1, 1);  /* Find player by name */
  717.   if (pn) {
  718.     getfirst(cmd); 
  719.     if (gCarg) {
  720.       free_svalue(gCarg->u.lvalue);
  721.       gCarg->u.lvalue->type = T_OBJECT;
  722.       gCarg->u.lvalue->u.ob = pn;
  723.       add_ref(pn, "parse_command(%l)");
  724.     }
  725.   }
  726.   return pn;
  727. }
  728.  
  729. /* Find match to %p in pattern when a list of words has been supplied
  730. */
  731. int findword (cmd, v)
  732.     char **cmd;
  733.     VALUE *v;
  734. {
  735.   char *w;
  736.   VECTOR *p;
  737.   struct svalue sv;
  738.   int cnt,m,f;
  739.  
  740.   w = lookfirst(*cmd); lowercase(w); p=v->u.vec;
  741.   cnt=0; m=p->size; f= -1;
  742.   while (cnt<m) {
  743.     if (p->item[cnt].type == T_STRING) {
  744.       if (strcmp(p->item[cnt].u.string,w)==0) {
  745.     f=cnt; cnt=m;
  746.       }
  747.     }
  748.     cnt+=1;
  749.   }
  750.   if (f<0) return 0;
  751.   getfirst(cmd);
  752.   if (!f) return 1; /* Match and word in first element */
  753.   /*
  754.     Swap element 0 and f in array
  755.   */
  756.   sv=p->item[0]; p->item[0]=p->item[f]; p->item[f]=sv;
  757.   return 1;
  758. }
  759.  
  760. /* Find match to %p in pattern
  761. */
  762. int findprepos (cmd)
  763.     char **cmd;
  764. {
  765.   char *w;
  766.   static char *hard_prep[] = {"on","in","under","from","behind","beside",0};
  767.   SVALUE *v;
  768.   int cnt;
  769.  
  770.   if (gForprepos) {
  771.     v = gForprepos->u.lvalue;
  772.     if ((v != 0) && (v->type == T_POINTER)) return findword(cmd,v);
  773.   }
  774.  
  775.   /* No wordlist sent, use hard coded prepositions and return a string
  776.   */
  777.   w = lookfirst(*cmd); lowercase(w);
  778.   cnt=0; while (hard_prep[cnt]) {
  779.     if (strcmp(w,hard_prep[cnt])==0) {
  780.       getfirst(cmd); /* Skip this word */
  781.       if (gCarg) {
  782.     free_svalue(gCarg->u.lvalue);
  783.     gCarg->u.lvalue->type = T_STRING;
  784.     gCarg->u.lvalue->u.string = string_copy(w);
  785.     gCarg->u.lvalue->string_type = STRING_MALLOC;
  786.     return 1;
  787.       }
  788.     }
  789.     cnt++;
  790.   }
  791.   return 0;
  792. }
  793.  
  794. /* Find match to %o in pattern
  795. */
  796. int findsingle (cmd)
  797.     char **cmd;
  798. {
  799.   if (finditem(cmd,0)) {
  800.     if ((itnumalt()==1) && (gCarg)) {
  801.       free_svalue(gCarg->u.lvalue);
  802.       gCarg->u.lvalue->type = T_OBJECT;
  803.       gCarg->u.lvalue->u.ob=italt(1);
  804.       add_ref(gCarg->u.lvalue->u.ob, "parse_command(%o)");
  805.     }
  806.     return 1;
  807.   }
  808.   return 0;
  809. }
  810.  
  811. /* Get the first parsetype of the pattern
  812. */
  813. int get1ps (parsep, lin, skip)
  814.     char **parsep;
  815.     LVALUE **lin;
  816.     int skip;
  817. {
  818.   char *cod,ch;
  819.   int pt;
  820.   LVALUE *l;
  821.  
  822.   pt=EP; cod=getfirst(parsep); l= *lin;
  823.   ch=cod[0]; if (ch=='%') { ch=tolower(cod[1]); ch=cod[1]; }
  824.   switch (ch) {
  825.   case 'i':pt=IT; break;
  826.   case 'l':pt=US; break;
  827.   case 's':pt=TX; break;
  828.   case 'w':pt=W1; break;
  829.   case 'o':pt=SI; break;
  830.   case 'p':pt=PP; break;
  831.   case 'd':pt=NUM; break;
  832.   case '\'':sscanf(cod,"'%[^\']",gMword); pt=DTX; break;
  833.   case '[':sscanf(cod,"\[%[^\135]",gMword); pt=OTX; /* 135 is oct for ] */
  834.     if (gMword[strlen(gMword)-1]==']') gMword[strlen(gMword)-1]=0;
  835.     break;
  836.   case '/':pt=ALT; break;
  837.   }
  838.   if (gDebug) fprintf(stderr,"(%s,%s,%d,%c)",cod,gMword,pt,ch);
  839.   gCarg=0;
  840.   if ((skip) || (pt==DTX) || (pt==OTX) || (pt==ALT)) return pt;
  841.   if (l != gTopStack) { gForprepos=l; gCarg=l; l++; }
  842.   else { gCarg = 0; gForprepos=0; }
  843.   *lin=l;
  844.   return pt;
  845. }
  846.  
  847. /* Add word to the string that matches the latest %s
  848. */
  849. void addword (d, s)
  850.     char *d;
  851.     char *s;
  852. {
  853.   if ((strlen(d)+strlen(s))<(KLUDGELEN-2)) {
  854.     if (!EMPTY(d)) strcat(d," "); 
  855.     strcat(d,s);
  856.   }
  857.   if (gTxarg) {
  858.     free_svalue(gTxarg->u.lvalue);
  859.     gTxarg->u.lvalue->type = T_STRING;
  860.     gTxarg->u.lvalue->u.string = string_copy(d);
  861.     gTxarg->u.lvalue->string_type = STRING_MALLOC;
  862.   }
  863. }
  864.  
  865. /* Main function, called from interpret.c
  866. */
  867. int parse (cs, ob_or_array, ps, dest_args, num_arg)
  868.     char *cs, *ps;
  869.     struct svalue *ob_or_array, *dest_args;
  870.     int num_arg;
  871. {
  872.   /* Arguments:
  873.      string      Command
  874.      ob/arr      List of accessible objects or recurse start object
  875.      ps         parsepattern
  876.      destargs     lvalues.
  877.      num_arg     Number of lvalues.
  878.      */
  879.   
  880.   int altflag,         /* =1 (true) i altkedja, match har intr{ffat */
  881.   txflag,              /* = 1 om vi adderar text till str{ng */
  882.   ptyp;                /* Parsetype %o %i %l %p %s 'word' [word] / %w */
  883.   
  884.   char *parsep;             /* Parsepattern */
  885.   char *cmd;               /* Command to be parsed */
  886.   char *ops,*ocs;          /* Temporary parse and command */
  887.   char tx_jp[KLUDGELEN];   /* Fill up string for %s */
  888.   LVALUE *l;               /* Argument pointer in dest_args */
  889.   int new_routines();
  890.  
  891.   if (ob_or_array->type == T_OBJECT &&
  892.       (ob_or_array->u.ob->flags & O_DESTRUCTED))
  893.     return 0;
  894.   gDebug = 0;
  895.   if (gDebug) {
  896.     fprintf(stderr,"Hold on to your toes, entering JnAparse. ");
  897.   }
  898.  
  899.  
  900.   /* In mudlib 3.0 we will not have this
  901.   */
  902.   if (cs[0]=='@')
  903.         error("Unsupported @ construct.\n");
  904.  
  905.   ocs = cmd = (char *) string_copy(cs);
  906.   
  907.   /* Get the accessible objects
  908.    */
  909.   if (ob_or_array->type == T_OBJECT) makeobjlist(&gOblist,ob_or_array->u.ob);
  910.   else { /* Copy list of given accessible objects in reverse order */
  911.     VECTOR *v;
  912.     SVALUE *vv;
  913.     int cnt;
  914.     v=ob_or_array->u.vec; italt_new();
  915.     for (cnt=0;cnt<v->size;cnt++) {
  916.       vv = &(v->item[v->size-1-cnt]);
  917.       if (vv->type==T_OBJECT) italt_put(vv->u.ob);
  918.     }
  919.     gOblist=gPobjects; gPobjects=0;
  920.   }
  921.   
  922.   ops = parsep = (char *) string_copy(ps);
  923.   gPobjects=gOblist;
  924.   if (gDebug) fprintf(stderr,"Has made list of Acsobjects. %d \n",itnumalt());
  925.   if (gDebug) fprintf(stderr,"Parsing: %s, with pattern: %s\n",cmd,parsep);
  926.   gPobjects=0;
  927.  
  928.   /* Start parsing
  929.    */
  930.   txflag = -1; gCarg = 0; gTxarg = 0; gTopStack = dest_args + num_arg;
  931.   l = dest_args;
  932.  
  933.   ptyp=get1ps(&parsep,&l,0); /* Get first pattern from parse */
  934.  
  935.   while (ptyp != EP) {
  936.     if (gDebug) fprintf(stderr,"Pattern: %d\n",ptyp);
  937.     altflag=0;
  938.     switch(ptyp) { /* See which pattern type to search for */
  939.  
  940.     case EP: break;
  941.       
  942.     case SI: if (findsingle(&cmd)) altflag=1; /* %o */ break;
  943.     case IT: if (findobject(&cmd)) altflag=1; /* %i */ break;
  944.     case US: if (findplay(&cmd)) altflag=1;   /* %l */ break;
  945.     case PP: if (findprepos(&cmd)) altflag=1; /* %p */ break;
  946.  
  947.     case TX: /* %s */
  948.       txflag=1; strcpy(tx_jp,""); gTxarg=gCarg; altflag=1; 
  949.       break;
  950.       
  951.     case DTX: /* 'word' */
  952.       if (EQ(lowercase(gMword),lowercase(lookfirst(cmd)))) {
  953.     getfirst(&cmd); altflag=1;
  954.       }
  955.       break;
  956.  
  957.     case OTX: /* [word] */
  958.       if (EQ(lowercase(gMword),lowercase(lookfirst(cmd)))) {
  959.     getfirst(&cmd); 
  960.       }
  961.       altflag=1; /* Always take next parsepattern type [word] is opt */
  962.       break;
  963.  
  964.     case ALT: /* / */
  965.       altflag=1; /* Should not be found here, if so skip it */
  966.  
  967.     case W1: /* %w */
  968.       gTxarg=gCarg; strcpy(tx_jp,""); altflag=1;
  969.       addword(tx_jp,getfirst(&cmd));
  970.       break;
  971.  
  972.     case NUM: /* %d */
  973.       if ((altflag=numeric(lookfirst(cmd)))>0) {
  974.     if (gCarg) {
  975.       free_svalue(gCarg->u.lvalue);
  976.       gCarg->u.lvalue->type = T_NUMBER;
  977.       gCarg->u.lvalue->u.number = altflag;
  978.     }
  979.     altflag=1; getfirst(&cmd);
  980.       }
  981.       break;
  982.     }
  983.  
  984.     /* Pattern checked altflag==1 indicates match
  985.     */
  986.     if (altflag) { /* Pattern matched, fetch next and end string input */
  987.       if (ptyp != TX) txflag = -1; /* End string input if not just started */
  988.       ptyp=get1ps(&parsep,&l,0);
  989.       while (ptyp == ALT) { /* Skip left over alternatives */
  990.     ptyp=get1ps(&parsep,&l,1); /* Skip this pattern */
  991.     ptyp=get1ps(&parsep,&l,0); /* Next real pattern or ALT */
  992.       }
  993.     }
  994.     else { /* Pattern did not match */
  995.       char *a;
  996.       LVALUE *try;
  997.       int tmp;
  998.       a=parsep; try=l;
  999.       tmp=get1ps(&a,&try,0);
  1000.       if (tmp == ALT) { 
  1001.     ptyp=get1ps(&parsep,&l,0); /* Skip ALT */
  1002.     ptyp=get1ps(&parsep,&l,0); /* Next real pattern or ALT */
  1003.       }
  1004.       else {
  1005.     if (txflag>=0) { /* %s is defined, add word and try pattern again */
  1006.       addword(tx_jp,getfirst(&cmd));
  1007.     }
  1008.     else break; /* Impossible to match pattern, exit */
  1009.       }
  1010.     }
  1011.     
  1012.     if (gDebug) fprintf(stderr,"Pattern, after: %d\n",ptyp);
  1013.   } 
  1014.  
  1015.   /* End of pattern reached, what have got? What is left?
  1016.   */
  1017.   if (gDebug) fprintf(stderr,"Pattern ended\n");
  1018.  
  1019.   if (txflag>=0) { /* It ended with a %s, fill up the string */
  1020.     while (!EMPTY(cmd)) addword(tx_jp,getfirst(&cmd));
  1021.   }
  1022.  
  1023.   if (!EMPTY(cmd)) ptyp=ALT; /* No match so set ptyp != EP */
  1024.  
  1025.   /* Now clean up our mess, no alloced mem should remain
  1026.   */
  1027.   free(ocs); free(ops);
  1028.   if (gPobjects) italt_new(); /* Free alternate object list */
  1029.   if (gOblist) {
  1030.     gPobjects=gOblist; italt_new(); /* Free list of accessible objects */
  1031.   }
  1032.   if (ptyp==EP) {
  1033.     if (gDebug) fprintf(stderr,"Exiting Jnaparse with match\n");
  1034.     return 1; /* Successfull match */
  1035.   }
  1036.   else {
  1037.     if (gDebug) fprintf(stderr,"Exiting Jnaparse: No match\n");
  1038.     return 0; /* No match */
  1039.   }
  1040. }
  1041.  
  1042. /*
  1043.  
  1044.    End of Parser
  1045.  
  1046. ***************************************************************/
  1047.  
  1048. #endif
  1049.